const sqlite3 = require("sqlite3");

let db;
const funcs = module.exports = {};
const statics = {};

funcs.statics = statics;

funcs.getUserByName = async (name) => {
    return new Promise(r => {
        db.get('SELECT user.id,user.username,user.password FROM user WHERE user.username=? LIMIT 1;', [name], (err, res) => {
            if (err) APP.error('DB - getUserByName', err);
            r(res);
        });
    });
}
funcs.createUrl = async (user, url, expiresDay) => {
    let time = Date.now();
    let expires = Math.max(0, parseInt(expiresDay) || 0);
    return new Promise(async r => {

        let id = await newUrlID();
        id = APP.tools.radixtoMax(id);

        db.get('INSERT INTO "main"."urls"("id","url","by","time","expires")VALUES(?,?,?,?,?);', [id, url, user, time, expires], (err, res) => {
            if (err) APP.error('DB - createUrl', err);
            r(id);
        });
    });
}
funcs.getUrl = async (id) => {
    return new Promise(r => {
        db.get("SELECT urls.url FROM urls WHERE urls.id=? LIMIT 1;", id, (err, res) => {
            if (err) APP.error('DB - getUrl', err);
            r((res || {}).url);
        });
    });
}

async function newUrlID() {
    let id = ++(statics.url_counter);
    let err = await new Promise(r => db.run("UPDATE stat SET v=? WHERE stat.k='url_counter';", [id.toString()], r));
    if (err) APP.error('DB - newUrlID', err);
    return id;
}
//init
(() => {

    db = new sqlite3.Database("./data.db", sqlite3.OPEN_READWRITE, (err) => {
        if (err) throw new Error("Init DB:" + err);
        else START_WAIT("DB");

        let dataWaiting = new Set();
        let over = false;
        let finishData = (name, info) => {
            if (name) {
                dataWaiting.delete(name);
                APP.info("DB", `${name}: ${info}`);
            } else over = true;
            if (!over || dataWaiting.size > 0) return;
            START_WAIT("DB_static");
        }

        let staticGetter = (field, name, defSupplier, trans = x => x, showValue = true) => {
            dataWaiting.add(field);
            db.get("SELECT stat.v FROM stat WHERE stat.k=? LIMIT 1;", [field], (err, res) => {
                if (err) throw new Error(`无法获取静态数据(${name},${field}): ${err}`);
                if (res) {
                    let v = trans(res.v);
                    statics[field] = v;
                    finishData(field, showValue ? (v + "").yellow : name.blue);
                } else {
                    let v = defSupplier();
                    db.run('INSERT INTO "main"."stat"("k","v")VALUES(?,?);', [field, v], (err, res) => {
                        if (err) throw new Error(`无法新建静态数据(${name},${field}): ${err}`);
                        statics[field] = v;
                        finishData(field, showValue ? (v + "").yellow : name.blue);
                    });
                }
            });
        };
        staticGetter('url_counter', '网址计数器', () => 0, str => BigInt(str));
        staticGetter('public_salt', '公共盐', () => APP.tools.randomString(16), x => APP.public_salt = x);
        staticGetter('private_token', '服务器私钥', () => APP.tools.randomString(32), x => APP.token_private = x, false);
        finishData();

    });



})();